from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.db.models import Q
from system.models import Dictionary, DictionaryItem
from system.SysUtils.permission import permission_required, data_permission_required
from .dicts_serializers import DictListSerializer, DictDetailSerializer, DictItemSerializer, DictCreateSerializer, DictUpdateSerializer, DictItemCreateSerializer, DictItemUpdateSerializer
import jwt
from django.conf import settings
from django.shortcuts import get_object_or_404


class DictView(APIView):
    """字典管理视图"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    
    @permission_required(["sys:dict:query"])
    def get(self, request, *args, **kwargs):
        """
        获取字典分页列表
        
        查询参数:
        - keywords: 关键字(字典名称或编码)
        - pageNum: 页码
        - pageSize: 每页记录数
        """
        # 获取查询参数
        keywords = request.query_params.get('keywords', '')
        page_num = request.query_params.get('pageNum', '1')
        page_size = request.query_params.get('pageSize', '10')
        
        # 转换页码和每页记录数为整数
        try:
            page_num = int(page_num)
            page_size = int(page_size)
            # 边界检查
            if page_num < 1:
                page_num = 1
            if page_size < 1:
                page_size = 10
        except ValueError:
            return Response({
                "code": "A0400",
                "msg": "页码或每页记录数格式不正确"
            }, status=400)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        data_permission = data_permission_required(token, "select")
        
        # 构建查询条件
        query = Q(is_deleted=0)
        
        # 添加数据权限过滤
        if isinstance(data_permission, list) and data_permission:
            # 如果返回的是用户ID列表，只查询这些用户创建的字典
            query &= Q(create_by__in=data_permission)
        
        # 添加关键字搜索
        if keywords:
            query &= (Q(name__icontains=keywords) | Q(dict_code__icontains=keywords))
        
        # 查询总记录数
        total = Dictionary.objects.filter(query).count()
        
        # 计算偏移量
        offset = (page_num - 1) * page_size
        
        # 查询分页数据
        dicts = Dictionary.objects.filter(query).order_by('-id')[offset:offset + page_size]
        
        # 序列化
        serializer = DictListSerializer(dicts, many=True)
        
        # 返回数据
        return Response({
            "code": "00000",
            "data": {
                "list": serializer.data,
                "total": total
            },
            "msg": "一切ok"
        })
    
    @permission_required(["sys:dict:add"])
    def post(self, request, *args, **kwargs):
        """
        创建字典
        
        请求体:
        {
          "name": "字典名称",
          "dictCode": "dict_code",
          "remark": "备注",
          "status": 1
        }
        """
        # 从token中获取用户ID
        token = request.headers.get("Authorization")
        user_id = None
        if token and token.startswith("Bearer "):
            token = token.split(" ")[1]
            try:
                # 解码token获取用户ID
                decoded_token = jwt.decode(token, settings.SIMPLE_JWT.get('SIGNING_KEY', settings.SECRET_KEY), algorithms=["HS256"])
                user_id = decoded_token.get('user_id')
            except jwt.InvalidTokenError:
                pass
        
        # 创建序列化器
        serializer = DictCreateSerializer(data=request.data, context={'user_id': user_id})
        
        # 验证数据
        if serializer.is_valid():
            # 保存字典
            dict_obj = serializer.save()
            
            # 序列化返回的字典数据
            response_serializer = DictDetailSerializer(dict_obj)
            
            # 返回成功响应
            return Response({
                "code": "00000",
                "data": response_serializer.data,
                "msg": "字典创建成功"
            })
        else:
            # 返回验证错误
            return Response({
                "code": "A0400",
                "msg": serializer.errors
            }, status=400)
    
    @permission_required(["sys:dict:edit"])
    def put(self, request, *args, **kwargs):
        """
        更新字典
        
        路径参数:
        - id: 字典ID
        
        请求体:
        {
          "name": "字典名称",
          "dictCode": "dict_code",
          "remark": "备注",
          "status": 1
        }
        """
        # 获取字典ID
        dict_id = kwargs.get('id')
        
        # 获取字典对象，如果不存在则返回404
        dict_obj = get_object_or_404(Dictionary, id=dict_id, is_deleted=0)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        user_id = None
        if token and token.startswith("Bearer "):
            token_str = token[7:]  # 去掉"Bearer "前缀
            data_permission = data_permission_required(token_str, "update", dict_obj.create_by)
            if data_permission is False:
                return Response({
                    "code": "A0401",
                    "msg": "无权限修改此字典"
                }, status=403)
            
            # 获取用户ID
            try:
                decoded_token = jwt.decode(token_str, settings.SIMPLE_JWT.get('SIGNING_KEY', settings.SECRET_KEY), algorithms=["HS256"])
                user_id = decoded_token.get('user_id')
            except jwt.InvalidTokenError:
                pass
        
        # 创建更新序列化器
        serializer = DictUpdateSerializer(dict_obj, data=request.data, context={'user_id': user_id})
        
        # 验证数据
        if serializer.is_valid():
            # 更新字典
            updated_dict = serializer.save()
            
            # 序列化返回数据
            response_serializer = DictDetailSerializer(updated_dict)
            
            # 返回成功响应
            return Response({
                "code": "00000",
                "data": response_serializer.data,
                "msg": "字典更新成功"
            })
        else:
            # 返回验证错误
            return Response({
                "code": "A0400",
                "msg": serializer.errors
            }, status=400)
    
    @permission_required(["sys:dict:delete"])
    def delete(self, request, *args, **kwargs):
        """
        删除字典
        
        路径参数:
        - id: 字典ID，多个以英文逗号(,)分割
        """
        # 获取字典ID
        dict_id = kwargs.get('id')
        
        if not dict_id:
            return Response({
                "code": "A0400",
                "msg": "请指定要删除的字典ID"
            }, status=400)
        
        # 处理多个ID的情况
        dict_ids = str(dict_id).split(',')
        
        # 转换为整数列表
        try:
            dict_ids = [int(did) for did in dict_ids if did]
        except ValueError:
            return Response({
                "code": "A0400",
                "msg": "字典ID格式不正确"
            }, status=400)
        
        if not dict_ids:
            return Response({
                "code": "A0400",
                "msg": "请指定要删除的字典ID"
            }, status=400)
        
        # 查询要删除的字典
        dicts_to_delete = Dictionary.objects.filter(id__in=dict_ids, is_deleted=0)
        
        # 检查是否存在要删除的字典项
        dict_codes = dicts_to_delete.values_list('dict_code', flat=True)
        if dict_codes:
            items_count = DictionaryItem.objects.filter(dict_code__in=dict_codes).count()
            if items_count > 0:
                return Response({
                    "code": "A0400",
                    "msg": "无法删除，存在关联的字典项"
                }, status=400)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        if token and token.startswith("Bearer "):
            token = token[7:]  # 去掉"Bearer "前缀
            
            # 检查每个字典的权限
            unauthorized_dicts = []
            for dict_obj in dicts_to_delete:
                data_permission = data_permission_required(token, "delete", dict_obj.create_by)
                if data_permission is False:
                    unauthorized_dicts.append(dict_obj.name)
            
            if unauthorized_dicts:
                return Response({
                    "code": "A0401",
                    "msg": f"无权限删除字典：{', '.join(unauthorized_dicts)}"
                }, status=403)
        
        # 执行逻辑删除（设置is_deleted=1）
        delete_count = dicts_to_delete.count()
        dicts_to_delete.update(is_deleted=1)
        
        # 返回成功响应
        return Response({
            "code": "00000",
            "data": {},
            "msg": f"成功删除{delete_count}个字典"
        })


class DictFormView(APIView):
    """字典表单数据视图"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    
    @permission_required(["sys:dict:query"])
    def get(self, request, *args, **kwargs):
        """
        获取字典表单数据
        
        路径参数:
        - id: 字典ID
        
        返回字典详细信息，用于表单编辑
        """
        # 获取字典ID
        dict_id = kwargs.get('id')
        
        # 获取字典对象，如果不存在则返回404
        dict_obj = get_object_or_404(Dictionary, id=dict_id, is_deleted=0)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        if token and token.startswith("Bearer "):
            token = token[7:]  # 去掉"Bearer "前缀
            
            # 检查是否有权限查看该字典
            data_permission = data_permission_required(token, "select", dict_obj.create_by)
            if data_permission is False:
                return Response({
                    "code": "A0401",
                    "msg": "无权限查看此字典"
                }, status=403)
        
        # 序列化字典数据，只返回表单所需字段
        serializer = DictDetailSerializer(dict_obj)
        form_data = {
            "id": serializer.data.get('id'),
            "name": serializer.data.get('name'),
            "dictCode": serializer.data.get('dictCode'),
            "remark": serializer.data.get('remark'),
            "status": serializer.data.get('status')
        }
        
        # 返回数据
        return Response({
            "code": "00000",
            "data": form_data,
            "msg": "一切ok"
        })


class DictItemView(APIView):
    """字典项管理视图"""
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    
    def get(self, request, *args, **kwargs):
        """
        获取字典项列表或字典项表单数据
        
        路径参数:
        - dictCode: 字典编码
        - itemId: 字典项ID (可选，如果提供则返回表单数据)
        
        查询参数:
        - keywords: 关键字(字典项值/字典项名称) (分页查询时使用)
        - pageNum: 页码 (分页查询时使用)
        - pageSize: 每页记录数 (分页查询时使用)
        """
        dict_code = kwargs.get('dict_code')
        item_id = kwargs.get('item_id')
        
        # 如果URL中包含 /page，则处理分页查询
        if request.path.endswith('/page'):
            return self._get_page_list(request, dict_code)
        # 如果URL中包含item_id并以/form结尾，则处理表单数据获取
        elif item_id is not None and request.path.endswith('/form'):
            return self._get_form_data(request, dict_code, item_id)
        # 否则处理简单列表获取
        else:
            return self._get_list(request, dict_code)
    
    @permission_required(["sys:dict-item:query"])
    def _get_form_data(self, request, dict_code, item_id):
        """获取字典项表单数据"""
        # 检查字典是否存在
        if not Dictionary.objects.filter(dict_code=dict_code, is_deleted=0).exists():
            return Response({
                "code": "A0404",
                "msg": f"字典编码 '{dict_code}' 不存在"
            }, status=404)
        
        # 获取字典项对象，如果不存在则返回404
        dict_item = get_object_or_404(DictionaryItem, id=item_id, dict_code=dict_code)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        if token and token.startswith("Bearer "):
            token = token[7:]  # 去掉"Bearer "前缀
            
            # 检查是否有权限查看该字典项
            data_permission = data_permission_required(token, "select", dict_item.create_by)
            if data_permission is False:
                return Response({
                    "code": "A0401",
                    "msg": "无权限查看此字典项"
                }, status=403)
        
        # 序列化字典项数据
        serializer = DictItemSerializer(dict_item)
        
        # 返回数据
        return Response({
            "code": "00000",
            "data": serializer.data,
            "msg": "一切ok"
        })
    
    @permission_required(["sys:dict-item:query"])
    def _get_page_list(self, request, dict_code):
        """获取字典项分页列表"""
        if not dict_code:
            return Response({
                "code": "A0400",
                "msg": "缺少字典编码"
            }, status=400)
        
        # 检查字典是否存在
        if not Dictionary.objects.filter(dict_code=dict_code, is_deleted=0).exists():
            return Response({
                "code": "A0404",
                "msg": f"字典编码 '{dict_code}' 不存在"
            }, status=404)
        
        # 获取查询参数
        keywords = request.query_params.get('keywords', '')
        page_num = request.query_params.get('pageNum', '1')
        page_size = request.query_params.get('pageSize', '10')
        
        # 转换页码和每页记录数为整数
        try:
            page_num = int(page_num)
            page_size = int(page_size)
            # 边界检查
            if page_num < 1:
                page_num = 1
            if page_size < 1:
                page_size = 10
        except ValueError:
            return Response({
                "code": "A0400",
                "msg": "页码或每页记录数格式不正确"
            }, status=400)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        data_permission = data_permission_required(token, "select")
        
        # 构建查询条件
        query = Q(dict_code=dict_code)
        
        # 添加数据权限过滤
        if isinstance(data_permission, list) and data_permission:
            # 如果返回的是用户ID列表，只查询这些用户创建的字典项
            query &= Q(create_by__in=data_permission)
        
        # 添加关键字搜索
        if keywords:
            query &= (Q(value__icontains=keywords) | Q(label__icontains=keywords))
        
        # 查询总记录数
        total = DictionaryItem.objects.filter(query).count()
        
        # 计算偏移量
        offset = (page_num - 1) * page_size
        
        # 查询分页数据
        dict_items = DictionaryItem.objects.filter(query).order_by('sort')[offset:offset + page_size]
        
        # 准备返回数据
        result_list = []
        for item in dict_items:
            result_list.append({
                "id": str(item.id),
                "dictCode": item.dict_code,
                "label": item.label,
                "value": item.value,
                "sort": item.sort,
                "status": item.status
            })
        
        # 返回数据
        return Response({
            "code": "00000",
            "data": {
                "list": result_list,
                "total": total
            },
            "msg": "一切ok"
        })
    
    def _get_list(self, request, dict_code):
        """获取字典项列表（不分页）"""
        if not dict_code:
            return Response({
                "code": "A0400",
                "msg": "缺少字典编码"
            }, status=400)
        
        # 检查字典是否存在
        if not Dictionary.objects.filter(dict_code=dict_code, is_deleted=0).exists():
            return Response({
                "code": "A0404",
                "msg": f"字典编码 '{dict_code}' 不存在"
            }, status=404)
        
        # 查询该字典编码下所有启用的字典项
        dict_items = DictionaryItem.objects.filter(
            dict_code=dict_code,
            status=1
        ).order_by('sort')
        
        # 准备返回数据
        result_list = []
        for item in dict_items:
            result_list.append({
                "value": item.value,
                "label": item.label,
                "tagType": item.tag_type
            })
        
        # 返回数据
        return Response({
            "code": "00000",
            "data": result_list,
            "msg": "一切ok"
        })
    
    @permission_required(["sys:dict-item:add"])
    def post(self, request, *args, **kwargs):
        """
        创建字典项
        
        路径参数:
        - dictCode: 字典编码
        
        请求体:
        {
          "label": "字典项标签",
          "value": "字典项值",
          "status": 1,
          "sort": 0,
          "tagType": "字典项类型"
        }
        """
        # 获取字典编码
        dict_code = kwargs.get('dict_code')
        if not dict_code:
            return Response({
                "code": "A0400",
                "msg": "缺少字典编码"
            }, status=400)
        
        # 检查字典是否存在
        dict_obj = Dictionary.objects.filter(dict_code=dict_code, is_deleted=0).first()
        if not dict_obj:
            return Response({
                "code": "A0404",
                "msg": f"字典编码 '{dict_code}' 不存在"
            }, status=404)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        user_id = None
        if token and token.startswith("Bearer "):
            token_str = token[7:]  # 去掉"Bearer "前缀
            
            # 检查用户对该字典的操作权限
            data_permission = data_permission_required(token_str, "add", dict_obj.create_by)
            if data_permission is False:
                return Response({
                    "code": "A0401",
                    "msg": "无权限向此字典添加项"
                }, status=403)
            
            # 获取用户ID
            try:
                decoded_token = jwt.decode(token_str, settings.SIMPLE_JWT.get('SIGNING_KEY', settings.SECRET_KEY), algorithms=["HS256"])
                user_id = decoded_token.get('user_id')
            except jwt.InvalidTokenError:
                pass
        
        # 构建请求数据，确保dictCode字段与路径参数一致
        request_data = request.data.copy()
        request_data['dictCode'] = dict_code
        
        # 创建序列化器
        serializer = DictItemCreateSerializer(data=request_data, context={'user_id': user_id})
        
        # 验证数据
        if serializer.is_valid():
            # 保存字典项
            dict_item = serializer.save()
            
            # 序列化返回数据
            response_serializer = DictItemSerializer(dict_item)
            
            # 返回成功响应
            return Response({
                "code": "00000",
                "data": response_serializer.data,
                "msg": "字典项创建成功"
            })
        else:
            # 返回验证错误
            return Response({
                "code": "A0400",
                "msg": serializer.errors
            }, status=400)
        
    @permission_required(["sys:dict-item:edit"])
    def put(self, request, *args, **kwargs):
        """
        更新字典项
        
        路径参数:
        - dictCode: 字典编码
        - itemId: 字典项ID
        
        请求体:
        {
          "id": "字典项ID",
          "dictCode": "字典编码",
          "value": "字典项值",
          "label": "字典项标签",
          "sort": 排序,
          "status": 状态,
          "tagType": "标签类型"
        }
        """
        # 获取路径参数
        dict_code = kwargs.get('dict_code')
        item_id = kwargs.get('item_id')
        
        if not dict_code:
            return Response({
                "code": "A0400",
                "msg": "缺少字典编码"
            }, status=400)
            
        if not item_id:
            return Response({
                "code": "A0400",
                "msg": "缺少字典项ID"
            }, status=400)
        
        # 检查字典是否存在
        if not Dictionary.objects.filter(dict_code=dict_code, is_deleted=0).exists():
            return Response({
                "code": "A0404",
                "msg": f"字典编码 '{dict_code}' 不存在"
            }, status=404)
        
        # 获取字典项对象，如果不存在则返回404
        dict_item = get_object_or_404(DictionaryItem, id=item_id, dict_code=dict_code)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        user_id = None
        if token and token.startswith("Bearer "):
            token_str = token[7:]  # 去掉"Bearer "前缀
            
            # 检查用户对该字典项的修改权限
            data_permission = data_permission_required(token_str, "update", dict_item.create_by)
            if data_permission is False:
                return Response({
                    "code": "A0401",
                    "msg": "无权限修改此字典项"
                }, status=403)
            
            # 获取用户ID
            try:
                decoded_token = jwt.decode(token_str, settings.SIMPLE_JWT.get('SIGNING_KEY', settings.SECRET_KEY), algorithms=["HS256"])
                user_id = decoded_token.get('user_id')
            except jwt.InvalidTokenError:
                pass
        
        # 构建请求数据，确保dictCode字段与路径参数一致
        request_data = request.data.copy()
        request_data['dictCode'] = dict_code
        
        # 创建更新序列化器
        serializer = DictItemUpdateSerializer(dict_item, data=request_data, context={'user_id': user_id})
        
        # 验证数据
        if serializer.is_valid():
            # 更新字典项
            updated_dict_item = serializer.save()
            
            # 序列化返回数据
            response_serializer = DictItemSerializer(updated_dict_item)
            
            # 返回成功响应
            return Response({
                "code": "00000",
                "data": response_serializer.data,
                "msg": "字典项更新成功"
            })
        else:
            # 返回验证错误
            return Response({
                "code": "A0400",
                "msg": serializer.errors
            }, status=400)
    
    @permission_required(["sys:dict-item:delete"])
    def delete(self, request, *args, **kwargs):
        """
        删除字典项
        
        路径参数:
        - dictCode: 字典编码
        - itemId: 字典项ID，多个以英文逗号(,)分割
        """
        # 获取路径参数
        dict_code = kwargs.get('dict_code')
        item_id = kwargs.get('item_id')
        
        if not dict_code:
            return Response({
                "code": "A0400",
                "msg": "缺少字典编码"
            }, status=400)
            
        if not item_id:
            return Response({
                "code": "A0400",
                "msg": "请指定要删除的字典项ID"
            }, status=400)
        
        # 检查字典是否存在
        if not Dictionary.objects.filter(dict_code=dict_code, is_deleted=0).exists():
            return Response({
                "code": "A0404",
                "msg": f"字典编码 '{dict_code}' 不存在"
            }, status=404)
        
        # 处理多个ID的情况
        item_id_list = str(item_id).split(',')
        
        # 转换为整数列表
        try:
            item_id_list = [int(item_id) for item_id in item_id_list if item_id]
        except ValueError:
            return Response({
                "code": "A0400",
                "msg": "字典项ID格式不正确"
            }, status=400)
        
        if not item_id_list:
            return Response({
                "code": "A0400",
                "msg": "请指定要删除的字典项ID"
            }, status=400)
        
        # 查询要删除的字典项
        items_to_delete = DictionaryItem.objects.filter(id__in=item_id_list, dict_code=dict_code)
        
        # 检查是否找到了所有要删除的项
        if len(items_to_delete) != len(item_id_list):
            found_ids = set(items_to_delete.values_list('id', flat=True))
            missing_ids = [str(item_id) for item_id in item_id_list if item_id not in found_ids]
            return Response({
                "code": "A0404",
                "msg": f"未找到ID为 {', '.join(missing_ids)} 的字典项"
            }, status=404)
        
        # 检查数据权限
        token = request.headers.get("Authorization")
        if token and token.startswith("Bearer "):
            token = token[7:]  # 去掉"Bearer "前缀
            
            # 检查每个字典项的权限
            unauthorized_items = []
            for item in items_to_delete:
                data_permission = data_permission_required(token, "delete", item.create_by)
                if data_permission is False:
                    unauthorized_items.append(f"{item.label}(ID:{item.id})")
            
            if unauthorized_items:
                return Response({
                    "code": "A0401",
                    "msg": f"无权限删除以下字典项：{', '.join(unauthorized_items)}"
                }, status=403)
        
        # 执行删除
        delete_count = items_to_delete.count()
        items_to_delete.delete()
        
        # 返回成功响应
        return Response({
            "code": "00000",
            "data": {},
            "msg": f"成功删除{delete_count}个字典项"
        })
